﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ElFinder.Connector.Utils;
using System.Diagnostics;
using ICSharpCode.SharpZipLib.Zip;
//using ICSharpCode.SharpZipLib.GZip;
//using ICSharpCode.SharpZipLib.Tar;
using System.Collections;

namespace ElFinder.Connector.Commands
{
    public class Archive : ICommand
    {
        public string Current { get; set; }

        public string Type { get; set; }

        public IEnumerable<string> Targets { get; set; }

        public Archive(string current, string type, string targets)
        {
            this.Current = current;

            this.Type = type;

            this.Targets = targets.Split(",".ToCharArray());
        }

        #region ICommand Members

        public ElFinder.Connector.Responses.Response Execute()
        {
            var path = DirectoryUtils.GetRelativePathByHash(Current);

            //var ArcApp = Configuration.Configuration.ArcAppPath;

            //response.tree = folder.Tree;

            string ArcName = "";
            if (Targets.Count() == 1)
            {
                ArcName = new System.IO.DirectoryInfo(DirectoryUtils.GetFilePathByHash(Targets.First())).Name + ".zip";
            }
            else
            {
                ArcName = "Archive1.zip";
            }

            var arrFiles = new List<string>();

            foreach (string hashname in Targets)
            {
                string filename = DirectoryUtils.GetFilePathByHash(hashname);

                if (System.IO.File.Exists(filename))
                {
                    if (CheckThumb(filename))
                        arrFiles.Add(filename);
                }
                if (System.IO.Directory.Exists(filename))
                    arrFiles.AddRange(GetListFiles(filename));
            }

            var arrFolder = new List<string>();

            System.IO.FileStream fsOut = System.IO.File.Create(path + @"\" + ArcName);
            ZipOutputStream zipOS = new ZipOutputStream(fsOut);
            zipOS.SetLevel(9);

            try
            {
                foreach (string filename in arrFiles)
                {
                    var fi = new System.IO.FileInfo(filename);
                    var relativePath = fi.DirectoryName.Replace(path, "").TrimStart(new char[] { '\\' }).Replace("\\", "/") + "/";
                    if (relativePath.Length < 2)
                        relativePath = "";

                    if (!string.IsNullOrEmpty(relativePath) && !arrFolder.Contains(relativePath))
                    {
                        ZipEntry zipEntryR = new ZipEntry(relativePath);
                        zipOS.PutNextEntry(zipEntryR);
                        arrFolder.Add(relativePath);
                    }

                    ZipEntry zipEntry = new ZipEntry(relativePath + fi.Name);
                    zipOS.PutNextEntry(zipEntry);

                    System.IO.FileStream fs = System.IO.File.OpenRead(filename);
                    byte[] allByte = new byte[int.Parse(fs.Length.ToString())];
                    fs.Read(allByte, 0, allByte.Length);
                    fs.Close();

                    zipEntry.Size = allByte.Length;
                    zipOS.Write(allByte, 0, allByte.Length);
                }
            }
            finally
            {
                zipOS.IsStreamOwner = true;	// Makes the Close also Close the underlying stream
                zipOS.Close();

                fsOut.Close();
            }

            var folder = new Utils.Folder(path);

            var response = new Responses.ActionCompletedResponse();

            response.cwd = folder.Cwd;

            response.cdc = folder.Contents;

            response.select = new string[] { (path + @"\" + ArcName).Hash() };

            return response;
        }

        private bool CheckThumb(string filename)
        {
            return !(new System.IO.FileInfo(filename).isHidden());
        }

        private IEnumerable<string> GetListFiles(string Dir)
        {
            List<string> files = new List<string>();
            bool Empty = true;

            foreach (string file in System.IO.Directory.GetFiles(Dir)) // add each file in directory
            {
                if (CheckThumb(file))
                {
                    files.Add(file);
                    Empty = false;
                }
            }

            if (Empty)
            {
                if (System.IO.Directory.GetDirectories(Dir).Length == 0)
                {
                    files.Add(Dir + @"\");
                }
            }

            foreach (string dirs in System.IO.Directory.GetDirectories(Dir)) // recursive
            {
                foreach (string obj in GetListFiles(dirs))
                {
                    if (CheckThumb(obj))
                    {
                        files.Add(obj);
                    }
                }
            }
            return files; // return file list
        }

        #endregion
    }
}
